#pragma once

#include <vector>
#include <stdint.h>
#include <Eigen/Dense>

namespace  ldl_eigen
{
class RNN
{
public:
    RNN(int64_t input_size, int64_t hidden_size);

    /**
     * @param[in] input 输入数据，形状为(num_steps, batch_size, input_size)
     */
    void forward(const std::vector<std::vector<std::vector<float>>> &input);
    
    void backward();

private:
    /**
     * @brief 输入数据的维度
     */
    int64_t m_input_size{};

    /**
     * @brief 输出数据的维度
     */
    int64_t m_output_size{};

    /**
     * @brief 隐藏变量的维度
     */
    int64_t m_hidden_size{};

    /**
     * @brief 输入数据对隐藏层节点的权重
     */
    Eigen::MatrixXf m_weight_xh{};

    /**
     * @brief 隐藏数据对隐层节点的权重
     */
    Eigen::MatrixXf m_weight_hh{};

    /**
     * @brief 隐层偏置
     */
    Eigen::VectorXf m_bias_h{};

    /**
     * @brief 隐层对输出层的权重
     */
    Eigen::MatrixXf m_weight_ho{};

    /**
     * @brief 输出层偏置
     */
    Eigen::VectorXf m_bias_o{};

    /**
     * @brief 误差对输入数据对隐藏层节点的权重的偏导
     */
    Eigen::MatrixXf m_weight_xh_gradient{};

    /**
     * @brief 误差对隐藏数据对隐层节点的权重的偏导
     */
    Eigen::MatrixXf m_weight_hh_gradient{};

    /**
     * @brief 误差对隐层偏置的偏导
     */
    Eigen::VectorXf m_bias_h_gradient{};

    /**
     * @brief 误差对隐层对输出层的权重的偏导
     */
    Eigen::MatrixXf m_weight_ho_gradient{};

    /**
     * @brief 误差对输出层偏置的偏导
     */
    Eigen::VectorXf m_bias_o_gradient{};

    std::vector<std::vector<std::vector<float>>> m_output{};

    Eigen::VectorXf m_hidden_variable{};
};
}
